/**
 * 
 */
package wpmp.security.client.internal;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import wcommons.httputils.HttpUtils;
import wcommons.httputils.quickbean.RespInfo;
import wpmp.security.client.InitException;
import wpmp.security.client.SecurityConfig;
import wpmp.utils.quickbean.ButtonConfig;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;

/**
 * @author Wayne.Wang<5waynewang@gmail.com>
 * @since 2:38:22 PM Apr 30, 2014
 */
public class PmpButtonConfigUtils {

	private static final Log LOG = LogFactory.getLog(PmpButtonConfigUtils.class);

	private static final String LIST = "buttonConfig.do?action=list";

	private static final TypeReference<RespInfo<List<ButtonConfig>>> TYPE_REFERENCE = new TypeReference<RespInfo<List<ButtonConfig>>>() {
	};

	// 客户端缓存
	private static Map<String, ButtonConfig> CACHE = new HashMap<String, ButtonConfig>();

	private static final ScheduledExecutorService EXEC = Executors.newSingleThreadScheduledExecutor();

	/**
	 * <pre>
	 * </pre>
	 */
	public static void init() {
		if (LOG.isInfoEnabled()) {
			LOG.info("start to load ButtonConfig from RemoteServer");
		}
		// 首次加载
		try {
			final List<ButtonConfig> results = list();
			if (results == null) {
				throw new InitException("Failed to load ButtonConfig from RemoteServer");
			}
			final Map<String, ButtonConfig> cache = new HashMap<String, ButtonConfig>();
			for (ButtonConfig result : results) {
				cache.put(result.getKey(), result);
			}
			PmpButtonConfigUtils.CACHE = cache;
		}
		catch (Exception e) {
			throw new InitException("Error to load ButtonConfig from RemoteServer", e);
		}

		if (LOG.isInfoEnabled()) {
			LOG.info("Success to load ButtonConfig from RemoteServer");
		}

		EXEC.scheduleWithFixedDelay(new Runnable() {
			@Override
			public void run() {
				try {
					if (LOG.isDebugEnabled()) {
						LOG.debug("start to reload ButtonConfig from RemoteServer");
					}

					final List<ButtonConfig> results = list();
					if (results != null) {
						final Map<String, ButtonConfig> cache = new HashMap<String, ButtonConfig>();
						for (ButtonConfig result : results) {
							cache.put(result.getKey(), result);
						}
						PmpButtonConfigUtils.CACHE = cache;

						if (LOG.isDebugEnabled()) {
							LOG.debug("success to reload ButtonConfig from RemoteServer");
						}
					}
					else if (LOG.isWarnEnabled()) {
						LOG.warn("Failed to reload ButtonConfig from RemoteServer");
					}
				}
				catch (Exception e) {
					LOG.error("Error to getButtonConfigList from RemoteServer", e);
				}
			}
		}, SecurityConfig.getButtonConfigCacheTimeout(), SecurityConfig.getButtonConfigCacheTimeout(), TimeUnit.SECONDS);

		Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
			@Override
			public void run() {
				EXEC.shutdown();
			}
		}));
	}

	static List<ButtonConfig> list() {
		final Map<String, Object> params = new HashMap<String, Object>();
		final String result = HttpUtils.postForString(SecurityConfig.getAuthUrl(LIST), params);
		if (StringUtils.isBlank(result)) {
			LOG.error("can not get anything from AuthServer for getButtonConfigList");
			return null;
		}
		final RespInfo<List<ButtonConfig>> respInfo = JSON.parseObject(result, TYPE_REFERENCE);

		if (respInfo.isSuccess()) {
			return respInfo.getResult();
		}

		LOG.error("Failed to getButtonConfigList from RemoteServer, response: " + result);
		return null;
	}

	/**
	 * <pre>
	 * 从缓存中获取
	 * </pre>
	 * 
	 * @param key
	 * @return
	 */
	public static ButtonConfig get(String key) {
		return CACHE.get(key);
	}
}
